#!/usr/bin/env python
import json
import os
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.messagebox
import tkinter.filedialog
import tkinter.scrolledtext
import tkinter.font

import qrcode

import common


software = {'description': '二维码生成器', 'name': 'QRCoder', 'version': '1.0', 'date': '2020-3-4'}


class MainWindow(tk.Tk):
    def __init__(self):
        super().__init__()
        self.data_config = {}
        self.load_config()

        self.title(f"{software['description']} {software['name']} {software['version']}")
        self.resizable(0, 0)
        self.geometry(common.center_screen(self, 640, 480))

        fm_in = ttk.Frame(self)
        fm_in.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, anchor=tk.NW)

        group_1 = ttk.LabelFrame(fm_in, text="1. 预设参数", width=70)
        group_1.pack(padx=10, pady=10, fill=tk.X, anchor=tk.NW)

        fm = ttk.Frame(group_1)
        fm.pack(padx=4, pady=4, anchor=tk.W)
        ttk.Label(fm, text="前后缀预设", width=12, anchor=tk.W).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)
        list_prefix = tk.StringVar()
        self.combo_prefix = ttk.Combobox(fm, textvariable=list_prefix, state='readonly')
        self.fresh_prefix()
        self.combo_prefix.bind("<<ComboboxSelected>>", self.choose_prefix)
        self.combo_prefix.pack(side=tk.LEFT, padx=4, pady=0, fill=tk.X, expand=True, anchor=tk.W)
        ttk.Button(fm, text="设置", command=self.dlg_option).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)

        fm = ttk.Frame(group_1)
        fm.pack(padx=4, pady=4, fill=tk.X, expand=True, anchor=tk.W)
        ttk.Label(fm, text="文件名称导入", width=12, anchor=tk.W).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)
        ttk.Button(fm, text="浏览", command=self.import_directory).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)

        # 检查项目
        group_2 = ttk.LabelFrame(fm_in, text="2. 数据内容", width=60)
        group_2.pack(padx=10, fill=tk.X, anchor=tk.NW)

        fm = ttk.Frame(group_2)
        fm.pack(padx=4, pady=4, fill=tk.X, expand=True, anchor=tk.W)
        ttk.Label(fm, text="前缀", width=9, anchor=tk.W).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)
        self.entry_prefix = ttk.Entry(fm)
        self.entry_prefix.pack(side=tk.LEFT, padx=4, pady=0, fill=tk.X, expand=True, anchor=tk.W)

        fm = ttk.Frame(group_2)
        fm.pack(padx=4, pady=4, fill=tk.X, expand=True, anchor=tk.W)
        ttk.Label(fm, text="后缀", width=9, anchor=tk.W).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)
        self.entry_suffix = ttk.Entry(fm, width=40)
        self.entry_suffix.pack(side=tk.LEFT, padx=4, pady=0, fill=tk.X, expand=True, anchor=tk.W)

        fm = ttk.Frame(group_2)
        fm.pack(padx=4, pady=4, fill=tk.X, expand=True, anchor=tk.W)
        ttk.Label(fm, text="内容", width=9, anchor=tk.W).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)
        self.text_content = tk.scrolledtext.ScrolledText(fm, height=10)
        self.text_content.pack(side=tk.LEFT, padx=4, pady=0, fill=tk.X, expand=True, anchor=tk.W)

        # 检查项目
        group_2 = ttk.LabelFrame(fm_in, text="3. 输出参数", width=60)
        group_2.pack(padx=10, fill=tk.X, anchor=tk.NW)

        fm = ttk.Frame(group_2)
        fm.pack(padx=4, pady=4, fill=tk.X, expand=True, anchor=tk.W)
        ttk.Label(fm, text="输出文件夹", width=9, anchor=tk.W).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)
        self.entry_output = ttk.Entry(fm)
        self.entry_output.insert(0, self.data_config.get('output', ''))
        self.entry_output.pack(side=tk.LEFT, padx=4, pady=0, fill=tk.X, expand=True, anchor=tk.W)
        ttk.Button(fm, text="浏览", command=self.choose_output).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)

        # 计算按钮
        fm = ttk.Frame(fm_in)
        fm.pack(padx=4, pady=4, fill=tk.X, expand=True, anchor=tk.S)

        self.button_output = ttk.Button(fm, text=" \n生成二维码\n", command=self.on_button_output, width=20)
        self.button_output.pack(side=tk.RIGHT, padx=4, pady=8, anchor=tk.E)

        # 创建菜单条
        menu_bar = tk.Menu(self)
        self.config(menu=menu_bar)

        # 添加帮助菜单
        file_menu = tk.Menu(menu_bar, tearoff=0)
        file_menu.add_command(label="关于", command=self.dlg_about)
        menu_bar.add_cascade(label="帮助", menu=file_menu)

        # self.choose_prefix()

        self.mainloop()

    def fresh_prefix(self):
        self.combo_prefix['values'] = ([item for item in self.data_config['preset']])
        # self.combo_prefix.current(0)

    def choose_prefix(self, _=None):
        value = self.combo_prefix.get()
        self.entry_prefix.delete(0, tk.END)
        self.entry_prefix.insert(0, self.data_config['preset'][value]['prefix'])
        self.entry_suffix.delete(0, tk.END)
        self.entry_suffix.insert(0, self.data_config['preset'][value]['suffix'])

    def import_directory(self):
        path = tkinter.filedialog.askdirectory()
        list_file = os.listdir(path)

        list_name = [os.path.splitext(filename)[0] for filename in list_file]
        self.text_content.delete(0.0, tk.END)
        self.text_content.insert(0.0, '\n'.join(list_name))
        print(list_file)

    def choose_output(self):
        path = tkinter.filedialog.askdirectory()
        self.entry_output.delete(0, tk.END)
        self.entry_output.insert(0, path)
        self.data_config['output'] = path

    def on_button_output(self):
        try:
            prefix = self.entry_prefix.get()
            suffix = self.entry_suffix.get()
            contents = self.text_content.get(0.0, tk.END)
            output_path = self.entry_output.get()

            if not os.path.exists(output_path):
                tk.messagebox.showerror('错误', f'目标文件夹 {output_path} 不存在！')
                return

            for value in contents.split('\n'):
                if value:
                    filename = f'{output_path}\\{value}.png'
                    self.create_qrcode(filename=filename, content=f'{prefix}{value}{suffix}')

            # 保存参数
            self.store_config()

        except ValueError as e:
            tkinter.messagebox.showwarning('数据错误', e)
            return

    def dlg_option(self):
        dlg = Option(self)
        self.wait_window(dlg)
        self.fresh_prefix()

    def dlg_about(self):
        dlg_about = tk.Toplevel(self)
        dlg_about.attributes("-toolwindow", 1)
        dlg_about.title("关于")
        dlg_about.geometry(common.center_dialog(self, 320, 192))

        fm = tk.Frame(dlg_about, background='white', width=320, height=160)
        fm.pack()
        fm_name = ttk.Frame(fm)
        fm_name.grid(column=0, row=0, sticky='NESW')
        fm_user = ttk.Frame(fm)
        fm_user.grid(column=0, row=1, sticky='NESW')

        ft = tk.font.Font(family='微软雅黑', size=20, weight=tk.font.BOLD)
        ttk.Label(fm_name, text=" ").grid(column=0, row=0, sticky='NESW')
        ttk.Label(fm_name, text=software['description'], font=ft).grid(column=0, columnspan=2, row=1, sticky='NESW')
        ttk.Label(fm_name, text=" ").grid(column=0, row=2, sticky='NESW')

        ft = tk.font.Font(family='微软雅黑', size=10, weight=tk.font.BOLD)
        ttk.Label(fm_user, text="软件名称", font=ft, width=10).grid(column=0, row=0, sticky='E')
        ttk.Label(fm_user, text="版本号", font=ft, width=10).grid(column=0, row=1, sticky='E')
        ttk.Label(fm_user, text="更新日期", font=ft, width=10).grid(column=0, row=2, sticky='E')
        ttk.Label(fm_user, text=software['name']).grid(column=1, row=0, sticky='NESW')
        ttk.Label(fm_user, text=software['version']).grid(column=1, row=1, sticky='NESW')
        ttk.Label(fm_user, text=software['date']).grid(column=1, row=2, sticky='NESW')

        dlg_about.mainloop()

    @staticmethod
    def create_qrcode(filename, content):
        qr = qrcode.QRCode(version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=0)
        qr.add_data(content)
        qr.make(fit=True)

        img = qr.make_image()
        img.save(filename)

    def load_config(self):
        if not os.path.exists(os.path.expanduser('~/QRCoder')):
            os.mkdir(os.path.expanduser('~/QRCoder'))
        if os.path.exists(os.path.expanduser('~/QRCoder/config.json')):
            with open(os.path.expanduser('~/QRCoder/config.json'), 'r') as f:
                self.data_config.update(json.load(f))

        if 'preset' not in self.data_config:
            self.data_config['preset'] = {}

    def store_config(self):
        with open(os.path.expanduser('~/QRCoder/config.json'), 'w') as f:
            json.dump(self.data_config, f)


class Option(tk.Toplevel):
    def __init__(self, master):
        super().__init__()
        self.master = master

        self.grab_set()
        self.title("设置")
        self.geometry(common.center_screen(self, 480, 320))

        fm_dialog = tk.Frame(self)
        fm_dialog.pack(fill=tk.BOTH, expand=True)

        group_1 = ttk.LabelFrame(fm_dialog, text="前后缀预设参数")
        group_1.pack(padx=10, pady=10, fill=tk.X, expand=True, anchor=tk.NW)

        fm = ttk.Frame(group_1)
        fm.pack(padx=4, pady=4, anchor=tk.W)
        ttk.Button(fm, text="新增", command=self.new_prefix).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)
        ttk.Button(fm, text="编辑", command=self.edit_prefix).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)
        ttk.Button(fm, text="保存", command=self.save_prefix).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)
        ttk.Button(fm, text="删除", command=self.delete_prefix).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)

        fm = ttk.Frame(group_1)
        fm.pack(padx=4, pady=4, anchor=tk.W)
        ttk.Label(fm, text="预设", width=6, anchor=tk.W).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)
        list_prefix = tk.StringVar()
        self.combo_prefix = ttk.Combobox(fm, textvariable=list_prefix, state='readonly')
        self.fresh_prefix()
        self.combo_prefix.bind("<<ComboboxSelected>>", self.choose_prefix)
        self.combo_prefix.pack(side=tk.LEFT, padx=4, pady=0, fill=tk.X, expand=True, anchor=tk.W)

        fm = ttk.Frame(group_1)
        fm.pack(padx=4, pady=4, fill=tk.X, expand=True, anchor=tk.W)
        ttk.Label(fm, text="名称", width=6, anchor=tk.W).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)
        self.entry_name = ttk.Entry(fm)
        self.entry_name.config(state=tk.DISABLED)
        self.entry_name.pack(side=tk.LEFT, padx=4, pady=0, fill=tk.X, expand=True, anchor=tk.W)

        fm = ttk.Frame(group_1)
        fm.pack(padx=4, pady=4, fill=tk.X, expand=True, anchor=tk.W)
        ttk.Label(fm, text="前缀", width=6, anchor=tk.W).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)
        self.entry_prefix = ttk.Entry(fm)
        self.entry_prefix.config(state=tk.DISABLED)
        self.entry_prefix.pack(side=tk.LEFT, padx=4, pady=0, fill=tk.X, expand=True, anchor=tk.W)

        fm = ttk.Frame(group_1)
        fm.pack(padx=4, pady=4, fill=tk.X, expand=True, anchor=tk.W)
        ttk.Label(fm, text="后缀", width=6, anchor=tk.W).pack(side=tk.LEFT, padx=4, pady=0, anchor=tk.W)
        self.entry_suffix = ttk.Entry(fm)
        self.entry_suffix.config(state=tk.DISABLED)
        self.entry_suffix.pack(side=tk.LEFT, padx=4, pady=0, fill=tk.X, expand=True, anchor=tk.W)

        # self.choose_prefix()

    def fresh_prefix(self, index=0):
        self.combo_prefix['values'] = ([value for value in self.master.data_config['preset']])
        self.combo_prefix.current(index)

    def choose_prefix(self, _=None):
        value = self.combo_prefix.get()
        self.entry_name.config(state=tk.NORMAL)
        self.entry_name.delete(0, tk.END)
        self.entry_name.insert(0, value)
        self.entry_name.config(state=tk.DISABLED)
        self.entry_prefix.config(state=tk.NORMAL)
        self.entry_prefix.delete(0, tk.END)
        self.entry_prefix.insert(0, self.master.data_config['preset'][value]['prefix'])
        self.entry_prefix.config(state=tk.DISABLED)
        self.entry_suffix.config(state=tk.NORMAL)
        self.entry_suffix.delete(0, tk.END)
        self.entry_suffix.insert(0, self.master.data_config['preset'][value]['suffix'])
        self.entry_suffix.config(state=tk.DISABLED)

    def new_prefix(self):
        self.entry_name.config(state=tk.NORMAL)
        self.entry_name.delete(0, tk.END)
        self.entry_prefix.config(state=tk.NORMAL)
        self.entry_prefix.delete(0, tk.END)
        self.entry_suffix.config(state=tk.NORMAL)
        self.entry_suffix.delete(0, tk.END)

    def edit_prefix(self):
        self.entry_prefix.config(state=tk.NORMAL)
        self.entry_suffix.config(state=tk.NORMAL)

    def save_prefix(self):
        name = self.entry_name.get()
        prefix = self.entry_prefix.get()
        suffix = self.entry_suffix.get()

        if not name:
            tk.messagebox.showerror('错误', '名称不能为空！')
            return
        if not prefix and not suffix:
            tk.messagebox.showerror('错误', '前缀和后缀不能同时为空！')
            return
        if name in self.master.data_config['preset']:
            if not tk.messagebox.askokcancel('确认', '名称已经存在，要覆盖么？'):
                return

        self.master.data_config['preset'][name] = {'prefix': prefix, 'suffix': suffix}
        self.master.store_config()
        self.fresh_prefix(len(self.master.data_config['preset']) - 1)
        self.choose_prefix()

    def delete_prefix(self):
        name = self.entry_name.get()
        if not tk.messagebox.askokcancel('确认', f'确实要删除 {name} 么？'):
            return
        del self.master.data_config['preset'][name]
        self.master.store_config()
        self.fresh_prefix(len(self.master.data_config['preset']) - 1)
        self.choose_prefix()


if __name__ == '__main__':
    frame = MainWindow()
